from django.contrib.auth.models import Group
from django.contrib.auth import get_user_model
from rest_framework import viewsets, permissions, status
from rest_framework.response import Response
from rest_framework.decorators import action
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from .serializers import GroupSerializer, UserSerializer, UserCreateSerializer, UserUpdateSerializer, UserLoginSerializer
from .permission import IsAdminUser

User = get_user_model()


class GroupViewSet(viewsets.ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    permission_classes = [permissions.IsAuthenticated]
    authentication_classes = [JSONWebTokenAuthentication]

    @action(detail=False, methods=['get'])
    def user_groups(self, request):
        user = request.user
        groups = user.groups.all()
        serializer = self.get_serializer(groups, many=True)
        return Response(serializer.data)

    def get_permissions(self):
        if self.action == 'create' or self.action == 'destroy':
            permission_classes = [IsAdminUser]
        else:
            permission_classes = [permissions.IsAuthenticated]
        return [permission() for permission in permission_classes]

    def destroy(self, request, *args, **kwargs):
        group = self.get_object()
        if group.user_set.exists():
            return Response({'error': 'Cannot delete group with users'}, status=status.HTTP_400_BAD_REQUEST)
        self.perform_destroy(group)
        return Response(status=status.HTTP_204_NO_CONTENT)


class IsAdminAndNotSelf(permissions.BasePermission):
    def has_permission(self, request, view):
        if not request.user.is_superuser:
            return False
        if view.action == 'delete_many':
            user_ids = request.data.get('user_ids', [])
            return request.user.id not in user_ids
        return False


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]
    authentication_classes = [JSONWebTokenAuthentication]

    def get_permissions(self):
        if self.action == 'delete_many':
            permission_classes = [IsAdminAndNotSelf]
        elif self.action == 'create' or self.action == 'destroy':
            permission_classes = [IsAdminUser]
        elif self.action == 'login':
            permission_classes = []
        else:
            permission_classes = [permissions.IsAuthenticated]
        return [permission() for permission in permission_classes]

    @action(detail=False, methods=['post'])
    def delete_many(self, request):
        user_ids = request.data.get('user_ids', [])
        if not user_ids:
            return Response({'error': 'user_ids parameter is required'}, status=status.HTTP_400_BAD_REQUEST)

        users = User.objects.filter(id__in=user_ids)

        users.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

    def get_serializer_class(self):
        if self.action == 'create':
            return UserCreateSerializer
        elif self.action == 'update':
            return UserUpdateSerializer
        elif self.action == 'login':
            return UserLoginSerializer
        else:
            return UserSerializer

    def partial_update(self, request, *args, **kwargs):
        password_old = request.data.get('password_old') or ''
        if not request.user.check_password(password_old):
            return Response({'error': 'The password you provided is incorrect.'}, status=status.HTTP_400_BAD_REQUEST)
        if str(kwargs.get('pk')) != str(request.user.id):
            return Response({'error': "You are not allowed to update other's info."}, status=status.HTTP_403_FORBIDDEN)
        return super().partial_update(request, *args, **kwargs)

    @action(detail=False, methods=['post'])
    def login(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        return Response(serializer.validated_data)

    @action(detail=False, methods=['post'])
    def logout(self, request):
        # JWT token is invalidated on the client side
        return Response({'success': 'Logged out successfully'})

    def get_queryset(self):
        if self.action != 'list' or not self.request.query_params.get('by_groupname'):
            return super().get_queryset()

        group_name = self.request.query_params.get('by_groupname')
        queryset = self.queryset.filter(groups__name=group_name)
        return queryset
